package com.xinsoft.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.constant.Const;
import com.xinsoft.entity.dto.*;
import com.xinsoft.entity.po.*;
import com.xinsoft.service.*;
import com.xinsoft.mapper.MesProducePlanMapper;
import com.xinsoft.utils.TokenUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author lijie
* @description 针对表【mes_produce_plan(生产计划)】的数据库操作Service实现
* @createDate 2023-07-24 09:25:01
*/
@Service
public class MesProducePlanServiceImpl extends ServiceImpl<MesProducePlanMapper, MesProducePlan>
    implements MesProducePlanService{

    @Resource
    public SysDictionaryService sysDictionaryService;

    @Resource
    public SysMaterialService sysMaterialService;

    @Resource
    public SysDeptService sysDeptService;

    @Resource
    public MesBomService mesBomService;

    @Resource
    public MesBomDetailService mesBomDetailService;

    @Resource
    public MesCraftService mesCraftService;

    @Resource
    public MesCraftProcessRefService mesCraftProcessRefService;

    @Resource
    public SysUserService sysUserService;

    @Resource
    public MesProducePlanHisService mesProducePlanHisService;

    @Resource
    public MesFeedingPlanService mesFeedingPlanService;

    @Resource
    public SysDocumentNumService sysDocumentNumService;

    @Resource
    public SysProjectService sysProjectService;

    @Resource
    public MesProcessPlanService mesProcessPlanService;

    @Override
    public IPage<MesProducePlanDTO> findPageListByParam(MesProducePlantParam param) {
        //分页
        Page<MesProducePlanDTO> page = new Page<MesProducePlanDTO>(param.getCurrentPage(), param.getPageSize());
        IPage<MesProducePlanDTO> resultPage = this.baseMapper.findListByParam(page, param);
        //返回值
        return resultPage;
    }

    @Override
    public MesProducePlanDTO findTotalByParam(MesProducePlantParam param) {
        MesProducePlanDTO resultPage = this.baseMapper.findTotalByParam(param);
        //返回值
        return resultPage;
    }

    @Override
    public JSONArray queryForAnalysis(MesProducePlantParam param) {


        JSONArray result = new JSONArray();
        //图一：生产计划进行状态
        JSONObject chat1 = new JSONObject();
        IPage<MesProducePlanDTO> page=  findPageListByParam(param);
        List<MesProducePlanDTO>  planList = page.getRecords();
        List<MesProducePlantChartDTO> list1 = new ArrayList<>();
        if(!CollectionUtils.isEmpty(planList)) {
            MesProducePlantChartDTO o1 = new MesProducePlantChartDTO();
            o1.setCount(0);
            o1.setAttName("正常进行");
            list1.add(o1);
            MesProducePlantChartDTO o2 = new MesProducePlantChartDTO();
            o2.setCount(0);
            o2.setAttName("开始延期");
            list1.add(o2);
            MesProducePlantChartDTO o3 = new MesProducePlantChartDTO();
            o3.setCount(0);
            o3.setAttName("结束延期");
            list1.add(o3);
            MesProducePlantChartDTO o4 = new MesProducePlantChartDTO();
            o4.setCount(0);
            o4.setAttName("开始结束均延期");
            list1.add(o4);

            for (MesProducePlanDTO mesProducePlanDTO : planList) {
                if (mesProducePlanDTO.getPlanStartTime() == null || mesProducePlanDTO.getPlanEndTime() == null) {
                    continue;
                }
                Date actStartTime = new Date();
                Date actEndTime = new Date();
                if (mesProducePlanDTO.getReleaseTime() != null) {
                    actStartTime = mesProducePlanDTO.getReleaseTime();
                }
                if (mesProducePlanDTO.getActualFinishTime() != null) {
                    actEndTime = mesProducePlanDTO.getActualFinishTime();
                }
                if (actStartTime.after(mesProducePlanDTO.getPlanStartTime())) {
                    if (actEndTime.after(mesProducePlanDTO.getPlanEndTime())) {
                        //开始结束均延期
                        o4.setCount(o4.getCount() + 1);
                    } else {
                        //开始延期
                        o2.setCount(o2.getCount() + 1);
                    }
                } else {
                    if (actEndTime.after(mesProducePlanDTO.getPlanEndTime())) {
                        //结束延期
                        o3.setCount(o3.getCount() + 1);
                    } else {
                        //正常进行
                        o1.setCount(o1.getCount() + 1);
                    }
                }
            }
        }
        chat1.put("name","计划进行状态");
        chat1.put("data",list1);
        result.add(chat1);

        //图二：生产计划状态
        JSONObject chat2 = new JSONObject();
        List list2=  this.baseMapper.getPlanForChat(param);
        chat2.put("name","计划状态");
        chat2.put("data",list2);
        result.add(chat2);
        //返回值
        return result;
    }






    @Override
    public MesProducePlanDTO getInfoById(Integer id) {
        MesProducePlanDTO result = new MesProducePlanDTO();
        MesProducePlan entity = this.getById(id);
        if(entity == null){
            return null;
        }
        BeanUtils.copyProperties(entity,result);
        // 原单类型
        SysDictionary sourceType = sysDictionaryService.getById(entity.getSourceType());
        if(sourceType!=null){
            result.setSourceTypeName(sourceType.getDicName());
        }

        // 物料信息
        SysMaterial material = sysMaterialService.getById(entity.getMaterialId());
        if(material!= null){
            result.setMaterialName(material.getMaterialName());
            result.setMaterialNo(material.getMaterialNo());
            result.setMaterialSpecific(material.getMaterialSpecific());
            // 住单位
            SysDictionary mainUom = sysDictionaryService.getById(material.getMainUnit());
            result.setMaterialMainUnitName(material.getMainUnitKis());
            if(mainUom!=null){
//                result.setMaterialMainUnitName(mainUom.getDicName());
            }
        }

        // 生产部门
        SysDept dept = sysDeptService.getById(entity.getDeptId());
        if(dept!=null){
            result.setDeptName(dept.getDeptName());
        }

        //辅助单位
        SysDictionary assistUom = sysDictionaryService.getById(entity.getAssistUom());
        if(assistUom!=null){
            result.setAssistUomName(assistUom.getDicName());
        }

        //生产类型
        SysDictionary produceType = sysDictionaryService.getById(entity.getProduceType());
        if(produceType!=null){
            result.setProduceTypeName(produceType.getDicName());
        }

        //BOM信息
        MesBom bom = mesBomService.getById(entity.getBomId());
        if(bom!=null){
            result.setBomNo(bom.getBomNo());
            result.setBomVersion(bom.getBomVersion());
            result.setDrawingNo(bom.getDrawingNo());
        }

        // 工艺路线
        MesCraft mesCraft = mesCraftService.getById(entity.getCraftId());
        if(mesCraft!=null){
            result.setCraftNo(mesCraft.getCraftNo());
            result.setCraftVersion(mesCraft.getCraftVersion());
            result.setCraftName(mesCraft.getCraftName());
        }

        //制单人
        SysUser user = sysUserService.getById(entity.getCreateBy());
        result.setCreateByName(user.getRealName());

        //项目
        SysProject project = sysProjectService.getById(entity.getId());
        if(project!=null){
            result.setProjectCode(project.getProjectCode());
        }

        return result;
    }

    @Override
    public void edit(MesProducePlanDTO planDTO) {
        MesProducePlan entity = getById(planDTO.getId());
        Integer planId = planDTO.getId();
        Integer status = entity.getPlanStatus();
        //结案状态下不允许变更
        if (Objects.equals(status, Const.producePlanStatus.CLOSE_CASE)
        || Objects.equals(status, Const.producePlanStatus.COMPLETE_WORK)
        ) {
            throw  new BDException("操作失败，结案或完工状态下不允许变更！");
        }

        //计划状态下的直接修改
        if (Objects.equals(status, Const.producePlanStatus.PLAN)) {
            BeanUtils.copyProperties(planDTO,entity);
            updateById(entity);
            return;
        }

        //其他状态下要保存变更记录，并更新工序计划

        BigDecimal oldPlanCount = entity.getPlanNum();
        BigDecimal newPlanCount = planDTO.getPlanNum();

        Date oldPlanStartTime = entity.getPlanStartTime();
        Date newPlanStartTime = planDTO.getPlanStartTime();

        Date oldPlanEndTime = entity.getPlanEndTime();
        Date newPlanEndTime = planDTO.getPlanEndTime();

        Integer oldProDept = entity.getDeptId();
        Integer newProDept = planDTO.getDeptId();

//        Map<String, Object> param = Maps.newHashMap();
//        List<WorkingProcedurePlanDO> procedurePlanList = this.getWorkingProcedurePlanList(planId, param);
//        if (procedurePlanList.size() > 0) {
//            Long procedurePlanId = procedurePlanList.get(0).getId();
//            List<Map<String, Object>> listByPlanId = workingProcedureDetailService.listByPlanId(procedurePlanId);
//            Map<String, Object> params;
//            for (Map<String, Object> map : listByPlanId) {
//                // XXX 循环调用查询是否有已开工的的工单 (可以使用批量查出方法)
//                params = Maps.newHashMap();
//                params.put("foriegnId", map.get("id"));
//                int count = dispatchItemService.count(params);
//                if (count > 0) {
//                    return R.error(messageSourceHandler.getMessage("plan.alteration.isSendOrders", null));
//                }
//            }
//            // 修改工序主表的数量
//            WorkingProcedurePlanDO procedurePlanDO = new WorkingProcedurePlanDO();
//            procedurePlanDO.setId(procedurePlanId);
//            procedurePlanDO.setCount(newPlanCount);
//            procedurePlanDO.setPlanStartTime(newPlanStartTime);
//            procedurePlanDO.setPlanEndTime(newPlanEndTime);
//            workingProcedurePlanService.update(procedurePlanDO);
//            // 修改工序子表的数量
//            WorkingProcedureDetailDO detailDO = new WorkingProcedureDetailDO();
//            detailDO.setPlanCount(newPlanCount);
//            detailDO.setPlanId(procedurePlanId);
//            workingProcedureDetailService.updateByPlanId(detailDO);
//        }

        MesProducePlanHis mesProducePlanHis;
        if (oldPlanCount.compareTo(newPlanCount) != 0) {
            mesProducePlanHis = new MesProducePlanHis();
            mesProducePlanHis.setProducePlanId(planId);
            mesProducePlanHis.setAfterValue(newPlanCount.toPlainString());
            mesProducePlanHis.setBeforeValue(oldPlanCount.toPlainString());
            mesProducePlanHis.setChangeField("计划生产数量");
            mesProducePlanHisService.save(mesProducePlanHis);
        }
        if (!oldPlanStartTime.equals(newPlanStartTime)) {
            mesProducePlanHis = new MesProducePlanHis();
            mesProducePlanHis.setProducePlanId(planId);
            mesProducePlanHis.setAfterValue(DateUtil.format(newPlanStartTime,"yyyy-MM-dd"));
            mesProducePlanHis.setBeforeValue(DateUtil.format(oldPlanStartTime,"yyyy-MM-dd"));
            mesProducePlanHis.setChangeField("计划开工时间");
            mesProducePlanHisService.save(mesProducePlanHis);
        }
        if (!oldPlanEndTime.equals(newPlanEndTime)) {
            mesProducePlanHis = new MesProducePlanHis();
            mesProducePlanHis.setProducePlanId(planId);
            mesProducePlanHis.setAfterValue(DateUtil.format(newPlanEndTime,"yyyy-MM-dd"));
            mesProducePlanHis.setBeforeValue(DateUtil.format(oldPlanEndTime,"yyyy-MM-dd"));
            mesProducePlanHis.setChangeField("计划完工时间");
            mesProducePlanHisService.save(mesProducePlanHis);
        }
        if (!Objects.equals(oldProDept, newProDept)) {
            mesProducePlanHis = new MesProducePlanHis();
            mesProducePlanHis.setProducePlanId(planId);
            mesProducePlanHis.setAfterValue(sysDeptService.getById(newProDept).getDeptName());
            mesProducePlanHis.setBeforeValue(sysDeptService.getById(oldProDept).getDeptName());
            mesProducePlanHis.setChangeField("生产部门");
            mesProducePlanHisService.save(mesProducePlanHis);
        }
        MesProducePlan productionPlan = new MesProducePlan();
        productionPlan.setId(planId);
        productionPlan.setPlanNum(newPlanCount);
        productionPlan.setPlanStartTime(newPlanStartTime);
        productionPlan.setPlanEndTime(newPlanEndTime);
        productionPlan.setDeptId(newProDept);
        this.updateById(productionPlan);
    }

    @Override
    public void create(MesProducePlanDTO planDTO) {
        MesProducePlan productionPlan = new MesProducePlan();
        BeanUtils.copyProperties(planDTO,productionPlan);
        productionPlan.setPlanStatus(Const.producePlanStatus.PLAN);
        this.save(productionPlan);
    }

    //检查BOM是否为空
    private boolean isBomEmpty(MesProducePlan planDO) {
        Integer type = planDO.getProduceType();
        // 是工序跟踪必须存在BOM
        if((type==Const.produceType.PROCESS_TRACKING || type==Const.produceType.PROJECT_MANUFACTURING)
                &&((1 == planDO.getDoCollect()) || (1 == planDO.getDoQuota()))
                &&(planDO.getBomId() == null)){
            return true;
        }
        return false;
    }

    //检查工艺路线是否为空
    private boolean isTecRouteEmpty(MesProducePlan planDO) {
        Integer type = planDO.getProduceType();
        // 检查生产类型是否为工序跟踪 或者 项目制造
        if (type == Const.produceType.ORDINARY_ORDER) {
            return false;
        }
        // 检查工序跟踪下 工艺路线是否为空
        if (type == Const.produceType.PROCESS_TRACKING && planDO.getCraftId() == null) {
            return true;
        }
        if (planDO.getCraftId() != null) {
            // 生成工序计划
            mesProcessPlanService.add(this.getProcedurePlanDO(planDO));
        }
        return false;
    }


    /**
     * 通过生产计划信息创建生产投料信息
     */
    private MesFeedingPlanDTO getFeedingDO(MesProducePlan producePlan) {
        MesFeedingPlanDTO feedingDTO = new MesFeedingPlanDTO();
        BeanUtils.copyProperties(producePlan, feedingDTO);
        feedingDTO.setProducePlanId(producePlan.getId());
        String feedingPlanNo = sysDocumentNumService.getSysDocumentNumByDocumentId(Const.DOCUMENT_ID.MES_FEEDING_PLAN_DOCUMENT);
        feedingDTO.setFeedingNo(feedingPlanNo);
        sysDocumentNumService.incrementLastSerialByDocumentId(Const.DOCUMENT_ID.MES_FEEDING_PLAN_DOCUMENT);
        return feedingDTO;
    }


    /**
     * 通过生产计划信息创建一个生产投料单子物料信息
     */
    private List<MesFeedingPlanDetailDTO> getFeedingDetails(MesProducePlan producePlan) {
        //用料采集
        Integer isCollect = producePlan.getDoCollect();
        QueryWrapper bomDetailQuery = new QueryWrapper<>();
        bomDetailQuery.eq("bom_id",producePlan.getBomId());
        List<MesBomDetail> list = mesBomDetailService.list(bomDetailQuery);
        // 获取所有物料详情
        List<Integer> materielIdList = list.stream()
                .map(MesBomDetail::getMaterialId)
                .distinct()
                .collect(Collectors.toList());

        QueryWrapper materialQuery = new QueryWrapper<>();

        materialQuery.in("id",materielIdList);
        List<SysMaterial> materielDOList = sysMaterialService.list(materialQuery);
        Map<Integer, Integer> facilityMap = materielDOList
                .stream()
                .collect(Collectors.toMap(SysMaterial::getId, v->v.getDefaultWhId()==null?0:v.getDefaultWhId()));
        Map<Integer, Integer> locationMap = materielDOList
                .stream()
                .collect(Collectors.toMap(SysMaterial::getId, v->v.getDefaultWhItemId()==null?0:v.getDefaultWhItemId()));

        List<MesFeedingPlanDetailDTO> feedingDetailList = new ArrayList<>();
        //获取数量精度
        Map<Integer, Integer> precision = sysMaterialService.getPrecision(list.stream().map(MesBomDetail::getMaterialId).distinct().collect(Collectors.toList())).get(1);
        Map<String, Object> feedingDetail;
        for (MesBomDetail bomDetailDO : list) {
            MesFeedingPlanDetailDTO mesFeedingPlanDetail = new MesFeedingPlanDetailDTO();
            Integer materielId = bomDetailDO.getMaterialId();
            mesFeedingPlanDetail.setMaterialId(materielId);
            // 计划投料数量公式 (标准用量 /(1-损耗率/100))*计划生产数量 -->  改为(主单位用量 /(1-损耗率/100))*计划生产数量
            BigDecimal wasteRate = bomDetailDO.getWasteRate();

            BigDecimal unitUomCount = bomDetailDO.getStandardCount() != null ? bomDetailDO.getStandardCount() : BigDecimal.ZERO;
            BigDecimal planCount = producePlan.getPlanNum();
            BigDecimal planFeeding = unitUomCount.divide(BigDecimal.valueOf(1 - wasteRate.doubleValue() / 100), precision.get(materielId),BigDecimal.ROUND_HALF_UP)
                    .multiply(planCount);
            //辅助单位计划投料数量 取bom 的 标准用量  (标准用量 /(1-损耗率/100))*计划生产数量 必须按主单位数量计算
            BigDecimal standardCount = bomDetailDO.getStandardCount() != null ? bomDetailDO.getStandardCount() : BigDecimal.ZERO;
            BigDecimal assistNum = standardCount.divide(BigDecimal.valueOf(1 - wasteRate.doubleValue() / 100), precision.get(materielId),BigDecimal.ROUND_HALF_UP)
                    .multiply(planCount);
            mesFeedingPlanDetail.setFeedingNum(planFeeding);
            // 新增字段
            //supportUom辅助单位主键   + planFeedingSupport  辅助单位投料数量 取bom 的 标准用量   +  换算单位
            mesFeedingPlanDetail.setAssistUom(bomDetailDO.getAssistUom());
            mesFeedingPlanDetail.setAssistNum(assistNum);
            mesFeedingPlanDetail.setConvCoefficient(bomDetailDO.getConvCoefficient());
            mesFeedingPlanDetail.setProcessId(bomDetailDO.getProcessId());
            mesFeedingPlanDetail.setStationId(bomDetailDO.getStationId());
            mesFeedingPlanDetail.setWarehouseId(facilityMap.get(materielId));
            mesFeedingPlanDetail.setWarehItemId(locationMap.get(materielId));
            mesFeedingPlanDetail.setIsCollect(isCollect);
            mesFeedingPlanDetail.setBomParentId(bomDetailDO.getParentBomId());
            mesFeedingPlanDetail.setBomDetailId(bomDetailDO.getId());

            feedingDetailList.add(mesFeedingPlanDetail);
        }
        return feedingDetailList;
    }

    /**
     * 下达
     * @param ids
     */
    @Override
    public void issuedPlans(List<Integer> ids) {
        for (Integer id : ids) {
            MesProducePlan producePlan = this.getById(id);
            //设置工艺路线id
            SysMaterial material = sysMaterialService.getById(producePlan.getMaterialId());
            producePlan.setCraftId(material.getCraftId());
            if (!Objects.equals(producePlan.getPlanStatus(), Const.producePlanStatus.PLAN)) {
                throw  new BDException("操作失败，只能下达状态为计划的生产计划");
            }

            if (this.isBomEmpty(producePlan)) {
                throw  new BDException("操作失败，项目制造和工序跟踪BOM不能为空！");
            }
            if (this.isTecRouteEmpty(producePlan)) {
                throw  new BDException("操作失败，项目制造和工序跟踪工艺路线不能为空！");
            }

            Integer type = producePlan.getProduceType();
            //如果 存在bom  且 为 普通订单 的生成投料计划
            // 项目制造与工序跟踪下可以生成BOM
            if (type != Const.produceType.ORDINARY_ORDER && producePlan.getBomId() != null) {
                //生产投料单据头信息
                MesFeedingPlanDTO feedingDTO = this.getFeedingDO(producePlan);
                //生产投料单子物料信息
                List<MesFeedingPlanDetailDTO> feedingDetails  =  this.getFeedingDetails(producePlan);
                feedingDTO.setMesFeedingPlanDetailList(feedingDetails);
                mesFeedingPlanService.addMesFeedingPlan(feedingDTO);
            }
            producePlan.setPlanStatus(Const.producePlanStatus.ISSUED);
            producePlan.setReleaseTime(new Date());
            producePlan.setReleasePersonId(TokenUtil.getUserId());
            this.updateById(producePlan);
        }
    }


    /**
     * 通过生产计划生成一个工序计划头单信息
     */
    private MesProcessPlanDTO getProcedurePlanDO(MesProducePlan producePlan) {
        MesProcessPlanDTO processPlan = new MesProcessPlanDTO();
        BeanUtils.copyProperties(producePlan, processPlan);
        if(Objects.equals(processPlan.getSourceType(),0)){
            processPlan.setSourceType(null);
        }

        processPlan.setProducePlanId(producePlan.getId());

        processPlan.setDoLimit(producePlan.getDoQuota());
        processPlan.setAssignId(null);
        processPlan.setAssignTime(null);
        processPlan.setActualFinishTime(null);
        // 生成工序明细
        List<MesProcessPlanDetailDTO> processPlanDetailList = this.baseMapper.getMesProcessPlanDetail(producePlan.getCraftId());
        processPlan.setMesProcessPlanDetailList(processPlanDetailList);
        return processPlan;
    }


    @Override
    public void reverseIssuedPlan(List<Integer> ids) {

        for (Integer id : ids) {
            MesProducePlan producePlan = this.getById(id);
            //判断工序计划状态为下达则，生产计划不允许反下达
            List<MesProcessPlan> processPlanList = mesProcessPlanService.list(new QueryWrapper<MesProcessPlan>().eq("produce_plan_id",id).ne("process_status",Const.producePlanStatus.PLAN));
            if(!CollectionUtils.isEmpty(processPlanList)){
                throw new BDException("操作失败，工序计划："+processPlanList.get(0).getProcessNo()+"已下达，生产计划："+producePlan.getPlanNo()+"不能反下达！");
            }
            //投料计划为审核状态 ，生产计划不允许反下达
            List<MesFeedingPlan> mesFeedingPlanList = mesFeedingPlanService.list(new QueryWrapper<MesFeedingPlan>().eq("produce_plan_id",id).eq("audit_status",1));
            if(!CollectionUtils.isEmpty(mesFeedingPlanList)){
                throw new BDException("操作失败，投料计划："+mesFeedingPlanList.get(0).getFeedingNo()+"已审核，生产计划："+producePlan.getPlanNo()+"不能反下达！");
            }

            // 删除工序计划
            mesProcessPlanService.remove(new QueryWrapper<MesProcessPlan>().eq("produce_plan_id",id));
            // 删除投料计划
            mesFeedingPlanService.remove(new QueryWrapper<MesFeedingPlan>().eq("produce_plan_id",id));

            producePlan.setPlanStatus(Const.producePlanStatus.PLAN);
            producePlan.setReleaseTime(null);
            producePlan.setReleasePersonId(null);
            updateById(producePlan);

        }
    }

    @Override
    public void putUp(List<Integer> ids) {
        for (Integer id : ids) {
            MesProducePlan producePlan = this.getById(id);
            producePlan.setPlanStatus(Const.producePlanStatus.PUT_UP);
            updateById(producePlan);
        }
    }

    @Override
    public void reversePutUp(List<Integer> ids) {
        for (Integer id : ids) {
            MesProducePlan producePlan = this.getById(id);
            producePlan.setPlanStatus(Const.producePlanStatus.ISSUED);
            updateById(producePlan);
        }
    }

    @Override
    public void close(List<Integer> ids) {
        for (Integer id : ids) {
            MesProducePlan producePlan = this.getById(id);
            producePlan.setPlanStatus(Const.producePlanStatus.CLOSE_CASE);
            updateById(producePlan);
        }
    }

    @Override
    public void reverseClose(List<Integer> ids) {
        for (Integer id : ids) {
            MesProducePlan producePlan = this.getById(id);
            producePlan.setPlanStatus(Const.producePlanStatus.ISSUED);
            updateById(producePlan);
        }
    }

    @Override
    public int insertOrUpdateBatch(List<MesProducePlan> planList) {
        return this.baseMapper.insertOrUpdateBatch(planList);
    }

    @Override
    public IPage<MesProductionExecutionFeedbackDTO> productionExecutionFeedback(MesProductionExecutionFeedbackParam param) {
        //作业单状态：1-未开始 2-加工中 3-已完成

        //未开始：生产计划---下达
        //       工序计划主页面---下达
        //       工序计划子页面工序明细---未派工/已派工
        //       生产执行反馈表---作业单状态：未开始
        //       工序明细状态：未派工/待生产
        //加工中：生产计划---下达
        //       工序计划主页面---下达
        //       工序计划子页面工序明细---已派工
        //       生产执行反馈表---作业单状态：加工中
        //       工序明细状态：生产中/已完成
        //       手机端报工页面派工单----开工/挂起/完工
        //已完成：生产计划---完工
        //       工序计划主页面---完工
        //       工序计划子页面工序明细---已完成
        //       生产执行反馈表---作业单状态：已完成
        //       工序明细状态：已完成

        // 查询生产计划和工序计划主数据状态 为 下达 和 完工的数据

        Page<MesProductionExecutionFeedbackDTO> page = new Page<>(param.getCurrentPage(), param.getPageSize());
        IPage<MesProductionExecutionFeedbackDTO> produceAndProcess = this.baseMapper.getProduceAndProcess(page, param);
        //返回值
        if(CollectionUtils.isEmpty(produceAndProcess.getRecords())){
            return produceAndProcess;
        }
        for (MesProductionExecutionFeedbackDTO record : produceAndProcess.getRecords()) {
            //判断状态，填充明细行
            List<MesProductionExecutionFeedbackDetailDTO> detailList = this.baseMapper.findProductionExecutionFeedbackDetail(record.getProcessPlanId());
            if(detailList.isEmpty()){
                record.setProductionExecutionStatus("未开始");
                record.setCompletionCount(BigDecimal.ZERO);
                continue;
            }
            // 生产计划 和 工序计划 都是下达状态 时
            if(Objects.equals(record.getProducePlanStatus(),Const.producePlanStatus.ISSUED) && Objects.equals(record.getProcessPlanStatus(),Const.producePlanStatus.ISSUED)){
                // 已完成数量
                BigDecimal totalCompleteNum = BigDecimal.ZERO;
                BigDecimal preCompleteNum = BigDecimal.ZERO;
                boolean startFlag = false;
                for (MesProductionExecutionFeedbackDetailDTO mesProductionExecutionFeedbackDetailDTO : detailList) {
                    //非待生产  时
                    if (!Objects.equals(mesProductionExecutionFeedbackDetailDTO.getDispatchStatus(),1)){
                        startFlag = true;
                    }
                    BigDecimal completeNum = mesProductionExecutionFeedbackDetailDTO.getCompleteNum()==null?BigDecimal.ZERO:mesProductionExecutionFeedbackDetailDTO.getCompleteNum();
                    if(completeNum.compareTo(mesProductionExecutionFeedbackDetailDTO.getPlanNum())>0){
                        completeNum = mesProductionExecutionFeedbackDetailDTO.getPlanNum();
                    }
                    totalCompleteNum = totalCompleteNum.add(completeNum);

                    // 前道完成数量
                    mesProductionExecutionFeedbackDetailDTO.setPreCompleteNum(preCompleteNum);
                    preCompleteNum = mesProductionExecutionFeedbackDetailDTO.getCompleteNum()==null?BigDecimal.ZERO:mesProductionExecutionFeedbackDetailDTO.getCompleteNum();

                    // 为工序明细反馈设置状态 未开始 生产中 已完成
                    if(Objects.equals(mesProductionExecutionFeedbackDetailDTO.getDispatchStatus(),Const.PlanType.dai_chan) &&
                            mesProductionExecutionFeedbackDetailDTO.getCompleteNum().compareTo(BigDecimal.ZERO)==0 ){
                        mesProductionExecutionFeedbackDetailDTO.setProcessStatus("待生产");

                    }else if(Objects.equals(mesProductionExecutionFeedbackDetailDTO.getDispatchStatus(),Const.PlanType.jie_an)
                    || Objects.equals(mesProductionExecutionFeedbackDetailDTO.getDispatchStatus(),Const.PlanType.wan_gong)){
                        mesProductionExecutionFeedbackDetailDTO.setProcessStatus("已完成");
                    }else{
                        mesProductionExecutionFeedbackDetailDTO.setProcessStatus("生产中");
                    }
                }
                // 判断 生产状态
                if(!startFlag && totalCompleteNum.compareTo(BigDecimal.ZERO)==0 ){
                    record.setProductionExecutionStatus("未开始");
                }else{
                    record.setProductionExecutionStatus("加工中");
                }
                // 设置完工数量
                record.setCompletionCount(totalCompleteNum);

                // 设置进度
                BigDecimal size = BigDecimal.valueOf(detailList.size());
                BigDecimal multiplyPlanNum = record.getPlanNum().multiply(size);
                BigDecimal s = (totalCompleteNum.divide(multiplyPlanNum,4,BigDecimal.ROUND_HALF_UP)).multiply(BigDecimal.valueOf(100)).setScale(0,BigDecimal.ROUND_HALF_UP);
                record.setProductionSchedule(s);

            }else{
                record.setProductionExecutionStatus("已完成");
                BigDecimal preCompleteNum = BigDecimal.ZERO;
                for (MesProductionExecutionFeedbackDetailDTO mesProductionExecutionFeedbackDetailDTO : detailList) {
                    mesProductionExecutionFeedbackDetailDTO.setProcessStatus("已完成");
                    // 前道完成数量
                    mesProductionExecutionFeedbackDetailDTO.setPreCompleteNum(preCompleteNum);
                    preCompleteNum = mesProductionExecutionFeedbackDetailDTO.getCompleteNum()==null?BigDecimal.ZERO:mesProductionExecutionFeedbackDetailDTO.getCompleteNum();
                }


                // 设置进度
                record.setProductionSchedule(BigDecimal.valueOf(100));
            }
            // 设置完工数量
            record.setCompletionCount(detailList.get(detailList.size()-1).getCompleteNum());
            record.setDetailList(detailList);
        }


        // 查询生产执行主数据明细行

        return produceAndProcess;
    }

    @Override
    public SysCountDTO getInProcessCount(){
        SysCountDTO result = new SysCountDTO();
        result.setName1("在制订单数");
        QueryWrapper queryWrapper = new QueryWrapper();
        int[] s = {2,3,5,6,7};
        queryWrapper.in("plan_status",s);
        queryWrapper.eq("audit_status",1);
        result.setValue1(String.valueOf(this.count(queryWrapper)));

        result.setName2("全部订单数");
        result.setValue2(String.valueOf(this.count()));
        return result;
    }


}






